#include <thread.h>
#include <units/work_queue.h>

#ifdef USE_WORK_QUEUE

static struct work_queue _work_queue;

void wait_queue_entry(void *parameter)
{
	struct work_queue_item *item;

	while(1) {
		item = work_queue_take_item();

		if (item != NULL) {
			item->call(item->args);
			free(item);
		} else {
			yield();
		}
	}
}

err_t work_queue_init(void)
{
	err_t ret = 0;
	struct thread *thread;

	_work_queue.parent.type = CLASS_TYPE_THREAD;
	ret = object_init(&_work_queue.parent, "w_queue");

	init_list(&_work_queue.item.list);

	thread = thread_creat("w_queue", wait_queue_entry, NULL, WORK_QUEUE_STACK_SIZE, WORK_PRIO);
	thread_start(thread);

	return ret;
}

err_t work_queue_register_item(void (*call) (void *args), void *args)
{
	struct work_queue_item *item;

	if (call == NULL)
		return -1;

	item = (struct work_queue_item *)malloc(sizeof(struct work_queue_item));

	item->call = call;
	item->args = args;

	list_add(&item->list, &_work_queue.item.list);

	return 0;
}

err_t work_queue_attach_item(struct work_queue_item *item)
{
	struct work_queue_item *tmp_item;

	/* 查找工作队列中是否已经存在当前项目 */
	list_for_each_entry(tmp_item, &_work_queue.item.list, list) {
		if (item == tmp_item)
			return -1;
	}

	list_add(&item->list, &_work_queue.item.list);

	return 0;
}

struct work_queue_item *work_queue_take_item(void)
{
	struct work_queue_item *item;

	if (list_empty(&_work_queue.item.list))
		return NULL;

	item = list_last_entry(&_work_queue.item.list, struct work_queue_item, list);

	list_del(&item->list);

	return item;
}
#endif
